/**
在 Webpack 中，"shimming" 是一种用于解决模块依赖和兼容性问题的技术，特别是在处理一些不支持模块化的库（如 jQuery、Lodash 等）时。通过 shimming，可以确保这些库在使用时能够正常工作，尤其是在与 ES6 模块或 CommonJS 模块的混合使用中。以下是关于 Webpack 中 shimming 的说明总结：

  1. 什么是 Shimming？
  Shimming 是指在使用不支持模块化的库时，通过创建一个适配层（shim）来确保这些库可以在模块化环境中正常使用。它的主要目的是解决依赖关系和全局变量的问题。

  2. Shimming 的应用场景
  - **全局变量依赖**: 一些库依赖于全局变量，而不是通过模块导入。例如，jQuery 通常通过 `window.$` 或 `window.jQuery` 访问。
  - **非模块化库**: 某些旧版库并不支持 AMD 或 CommonJS 模块化，直接使用时可能会导致错误。

  3. 在 Webpack 中实现 Shimming

   1. 使用 `ProvidePlugin`
  Webpack 提供了 `ProvidePlugin` 插件，可以自动加载模块，而不需要显式导入。它适用于需要在多个模块中使用的库。

   示例配置：

  ```javascript
  const webpack = require('webpack');

  module.exports = {
      // ...
      plugins: [
          new webpack.ProvidePlugin({
              $: 'jquery', // 将 jQuery 赋值给 $ 和 jQuery
              jQuery: 'jquery',
          }),
      ],
  };
  ```

  在这个配置中，`ProvidePlugin` 会在需要 `$` 或 `jQuery` 的地方自动加载 jQuery。

   2. 创建 Shim 模块
  如果需要更复杂的 shimming，可以手动创建一个 shim 模块，该模块负责将全局变量绑定到模块中。

   示例：

  ```javascript
  // shim.js
  import jQuery from 'jquery';

  window.$ = window.jQuery = jQuery; // 将 jQuery 绑定到全局变量

  export default jQuery; // 导出 jQuery
  ```

  然后在其他模块中导入这个 shim 模块：
  ```javascript
  // main.js
  import './shim'; // 引入 shim 模块
  import $ from 'jquery';

  $(document).ready(() => {
      console.log('jQuery is ready!');
  });
  ```

  4. 注意事项
  - **全局污染**: 使用 shimming 可能会导致全局命名空间的污染，因此需要谨慎管理全局变量。
  - **兼容性**: 确保 shim 模块的实现与其他模块的依赖关系兼容，以避免运行时错误。
  - **性能**: 过多的 shimming 可能会影响性能，因此应尽量使用支持模块化的库。

  总结
  在 Webpack 中，shimming 是一种解决模块依赖和兼容性问题的有效技术。通过使用 `ProvidePlugin` 或手动创建 shim 模块，开发者可以确保不支持模块化的库能够在现代 JavaScript 环境中正常工作。希望这个总结对你理解 Webpack 中的 shimming 有所帮助！
 */
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const { ProvidePlugin } = require("webpack");

module.exports = {
  mode: "production",
  devtool: false,
  entry: "./src/main.js",
  output: {
    clean: true,
    path: path.resolve(__dirname, "./build"),
    filename: "[name]_chunk.js",
  },
  /**
   * externals: 排除某些包不需要进行打包
   */
  // externals: {
  //   /**
  //    * key属性名: 排除的框架名称
  //    * value属性值: 从CDN地址请求下来的js中提供对应的名称
  //    */
  //   react: "React",
  //   axios: "axios",
  // },
  /**
   * resolve: 配置模块解析
   * extensions: 配置解析模块时自动补全的扩展名
   */
  resolve: {
    extensions: [".js", ".json", ".wasm", ".jsx", ".ts"],
  },
  devServer: {
    static: ["public", "content"],
    port: 3000,
    compress: true,
    proxy: [
      {
        context: () => true,
        target: "http://localhost:1234",
        pathRewrite: { "^/api": "" },
      },
    ],
    historyApiFallback: true,
  },
  optimization: {
    chunkIds: "deterministic", // 生成文件名时使用确定的文件名
    runtimeChunk: {
      name: "runtime", // 将runtime相关的代码单独打包
    },
    splitChunks: {
      // 分包配置
      chunks: "all", // 对所有模块都进行分割
      minSize: 10, // 分割的模块最小为10kb
      // 自己对需要进行拆包的内容进行分包
      cacheGroups: {
        utils: {
          test: /utils/,
          filename: "[id]_utils.js",
        },
        vendors: {
          // /node_modules/
          // window上面 /\
          // mac上面 /
          test: /[\\/]node_modules[\\/]/,
          filename: "[id]_vendors.js",
        },
      },
    },
    // 压缩配置
    minimizer: [
      new TerserPlugin({
        extractComments: false, // 不将注释提取到单独的文件中
      }),
    ],
  },
  module: {
    rules: [
      {
        test: /\.jsx$/,
        use: {
          loader: "babel-loader",
        },
      },
      {
        test: /\.js$/,
        use: "babel-loader",
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./index.html", // 模板文件
    }),
    new ProvidePlugin({
      axios: ["axios", "default"],
      dayjs: "dayjs",
    }),
  ],
};
